/**
 * Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com).
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.springblade.auth.controller;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.AllArgsConstructor;
import org.springblade.common.cache.CacheNames;
import org.springblade.common.constant.SecurityConstants;
import org.springblade.core.secure.AuthInfo;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.support.Kv;
import org.springblade.core.tool.utils.Func;
import org.springblade.core.tool.utils.RedisUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.provider.endpoint.TokenEndpoint;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.annotation.*;

import java.security.Principal;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * 认证模块
 *
 * @author Chill
 */
@RestController
@AllArgsConstructor
@Api(value = "用户授权认证", tags = "授权接口")
public class AuthController {

	private RedisUtil redisUtil;

	@Autowired
	private TokenEndpoint tokenEndpoint;

	@PostMapping("/oauth/token")
	@ApiOperation(value = "获取认证token", notes = "传入租户ID:tenantId,账号:account,密码:password")
	public R<AuthInfo> postAccessToken(@ApiParam(value = "授权类型", required = true) @RequestParam(defaultValue = "password", required = false) String grantType,
									   @ApiParam(value = "刷新令牌") @RequestParam(required = false) String refreshToken,
									   @ApiParam(value = "租户ID", required = true) @RequestParam(defaultValue = "000000", required = false) String tenantId,
									   @ApiParam(value = "权限空间") @RequestParam(defaultValue = "all",required = false)String scope,
									   @ApiParam(value = "账号")  @RequestParam(required = false)String account,
									   @ApiParam(value = "密码") @RequestParam(required = false)String password,
									   @ApiParam(value = "第三方登陆标识") @RequestParam(required = false)String providerId,
									   @ApiParam(value = "第三方登陆类型") @RequestParam(required = false)String providerType,
									   @RequestBody(required = false) String body,
									   Principal principal) throws HttpRequestMethodNotSupportedException {

//		if(body!=null){
//			JSONObject jsonObject=new JSONObject(body);
//			account=jsonObject.getStr("account");
//			password=jsonObject.getStr("password");
//		}
//		String userType = Func.toStr(WebUtil.getRequest().getHeader(TokenUtil.USER_TYPE_HEADER_KEY), TokenUtil.DEFAULT_USER_TYPE);
//
//		TokenParameter tokenParameter = new TokenParameter();
//		tokenParameter.getArgs().set("tenantId", tenantId).set("account", account).set("password", password).set("grantType", grantType).set("refreshToken", refreshToken).set("userType", userType);
//
//		ITokenGranter granter = TokenGranterBuilder.getGranter(grantType);
//		if (userType.equals(BladeUserEnum.WEB.getName())) {
//			UserInfo userInfo = granter.grant(tokenParameter);
//
//			if (userInfo == null || userInfo.getUser() == null || userInfo.getUser().getId() == null) {
//				return R.fail(TokenUtil.USER_NOT_FOUND);
//			}
//
//			return R.data(TokenUtil.createAuthInfo(userInfo));
//		}else if(userType.equals(BladeUserEnum.APP.getName())){
//			RegisteredInfo registeredInfo = granter.grantTo(tokenParameter);
//			if (registeredInfo == null || registeredInfo.getRegistered() == null || registeredInfo.getRegistered().getId() == null) {
//				return R.fail(TokenUtil.USER_NOT_FOUND);
//			}
//
//			return R.data(TokenUtil.createRegisteredAuthInfo(registeredInfo));
//		}
//		return R.fail(TokenUtil.USER_NOT_FOUND);
		Map<String, String> parameters = new HashMap<>();
		parameters.put("grant_type",grantType);
		parameters.put("username",account);
		parameters.put("password",password);
		parameters.put("providerId",providerId);
		parameters.put("providerType",providerType);
		parameters.put("scope",scope);
		return custom(tokenEndpoint.postAccessToken(principal,parameters).getBody());
	}

	@GetMapping("/oauth/token")
	@ApiOperation(value = "获取认证token", notes = "传入租户ID:tenantId,账号:account,密码:password")
	public R<AuthInfo> token(@ApiParam(value = "授权类型", required = true) @RequestParam(defaultValue = "password", required = false) String grantType,
							 @ApiParam(value = "刷新令牌") @RequestParam(required = false) String refreshToken,
							 @ApiParam(value = "租户ID", required = true) @RequestParam(defaultValue = "000000", required = false) String tenantId,
							 @ApiParam(value = "权限空间") @RequestParam(defaultValue = "all",required = false)String scope,
							 @ApiParam(value = "账号")  @RequestParam(required = false)String account,
							 @ApiParam(value = "密码") @RequestParam(required = false)String password,@RequestBody(required = false) String body,
							 Principal principal) throws HttpRequestMethodNotSupportedException {
		Map<String, String> parameters = new HashMap<>();
		parameters.put("grant_type",grantType);
		parameters.put("username",account);
		parameters.put("password",password);
		parameters.put("scope",scope);
		return custom(tokenEndpoint.getAccessToken(principal,parameters).getBody());
	}

	//自定义返回格式
	private R<AuthInfo> custom(OAuth2AccessToken accessToken) {
		DefaultOAuth2AccessToken token = (DefaultOAuth2AccessToken) accessToken;
		AuthInfo authInfo = new AuthInfo();
		authInfo.setAccessToken(token.getValue());
		authInfo.setRefreshToken(token.getRefreshToken().getValue());
		authInfo.setExpiresIn(token.getExpiresIn());
		authInfo.setAccount(Func.toStr(token.getAdditionalInformation().get(SecurityConstants.DETAILS_USER_ACCOUNT)));
		authInfo.setAuthority(Func.toStr(token.getAdditionalInformation().get(SecurityConstants.DETAILS_USER_ROLE_NAME)));
		authInfo.setLicense(Func.toStr(token.getAdditionalInformation().get(SecurityConstants.DETAILS_LICENSE)));
		authInfo.setAvatar(Func.toStr(token.getAdditionalInformation().get(SecurityConstants.DETAILS_USER_AVATAR)));
		authInfo.setTokenType(token.getTokenType());
		authInfo.setUserName(Func.toStr(token.getAdditionalInformation().get(SecurityConstants.DETAILS_USER_NAME)));
		return R.data(authInfo);
	}

}
